package com.ssy.lingxi.order.serviceimpl.base;

import com.ssy.lingxi.common.constant.marketing.BelongTypeEnum;
import com.ssy.lingxi.common.constant.marketing.MerchantCouponTypeEnum;
import com.ssy.lingxi.common.constant.marketing.PlatformCouponTypeEnum;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.order.entity.OrderCouponDO;
import com.ssy.lingxi.order.entity.OrderDO;
import com.ssy.lingxi.order.entity.OrderProductDO;
import com.ssy.lingxi.order.model.constant.OrderServiceContants;
import com.ssy.lingxi.order.model.dto.OrderSeparateDTO;
import com.ssy.lingxi.order.model.vo.basic.request.OrderCouponVO;
import com.ssy.lingxi.order.model.vo.vendor.response.VendorOrderCouponVO;
import com.ssy.lingxi.order.repository.OrderCouponRepository;
import com.ssy.lingxi.order.service.base.IBaseOrderCouponService;
import com.ssy.lingxi.order.utils.NumberUtil;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 订单关联的优惠券相关接口实现类
 * @author 万宁
 * @version 2.0.0
 * @date 2021-09-23
 */
@Service
public class BaseOrderCouponServiceImpl implements IBaseOrderCouponService {
    @Resource
    private OrderCouponRepository orderCouponRepository;

    /**
     * （拆单）根据拆单订单商品金额总和，加权平均计算拆单后的优惠券金额
     *
     * @param couponAmount       订单优惠券总金额
     * @param couponAmountMap 拆单订单商品金额总和
     * @return 拆单订单优惠券金额
     */
    @Override
    public Map<OrderSeparateDTO, BigDecimal> findSeparateOrderCouponAmount(BigDecimal couponAmount, Map<OrderSeparateDTO, BigDecimal> couponAmountMap) {
        if(NumberUtil.isNullOrZero(couponAmount)) {
            return couponAmountMap.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, p -> BigDecimal.ZERO));
        }

        BigDecimal totalAmount = couponAmountMap.values().stream().reduce(BigDecimal.ZERO, BigDecimal::add);
        if(totalAmount.compareTo(BigDecimal.ZERO) == 0) {
            return couponAmountMap.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, p -> BigDecimal.ZERO));
        }

        return couponAmountMap.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, p -> p.getValue().multiply(couponAmount).divide(totalAmount, 2, RoundingMode.HALF_UP)));
    }

    /**
     * （拆单）根据拆单订单商品金额总和，加权平均计算拆单后的优惠券金额
     *
     * @param separateSkuMap 拆单商品Sku列表
     * @param skuCouponMap   Sku优惠券减少的金额
     * @return 拆单订单优惠券金额
     */
    @Override
    public Map<OrderSeparateDTO, BigDecimal> findSeparateOrderCouponAmount(Map<OrderSeparateDTO, List<Long>> separateSkuMap, Map<Long, BigDecimal> skuCouponMap) {
        return separateSkuMap.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, skuIds -> skuCouponMap.entrySet().stream().filter(entry -> skuIds.getValue().contains(entry.getKey())).map(Map.Entry::getValue).reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, RoundingMode.HALF_UP)));
    }

    /**
     * 校验、保存订单关联的优惠券列表
     *
     * @param order   订单
     * @param coupons 优惠券列表
     * @return 保存结果
     */
    @Override
    public Wrapper<Void> checkOrderCoupons(OrderDO order, List<OrderCouponVO> coupons) {
        if(CollectionUtils.isEmpty(coupons)) {
            order.setCoupons(new HashSet<>());
            return Wrapper.success();
        }

        //过滤优惠券
        List<OrderCouponVO> availableCoupons = filterOrderCoupons(order, coupons);
        if(CollectionUtils.isEmpty(availableCoupons)) {
            order.setCoupons(new HashSet<>());
            return Wrapper.success();
        }

        List<OrderCouponDO> orderCoupons = availableCoupons.stream().distinct().map(c -> {
            OrderCouponDO coupon = new OrderCouponDO();
            coupon.setOrder(order);
            coupon.setCouponId(c.getCouponId());
            coupon.setName(c.getName());
            coupon.setCouponType(c.getCouponType());
            coupon.setBelongType(c.getBelongType());
            coupon.setAmount(c.getAmount());
            coupon.setStartTime(LocalDateTime.parse(c.getStartTime(), OrderServiceContants.DEFAULT_TIME_FORMATTER));
            coupon.setExpireTime(LocalDateTime.parse(c.getExpireTime(), OrderServiceContants.DEFAULT_TIME_FORMATTER));
            return coupon;
        }).collect(Collectors.toList());

        orderCouponRepository.saveAll(orderCoupons);

        order.setCoupons(new HashSet<>(orderCoupons));
        return Wrapper.success();
    }

    /**
     * 过滤订单使用的优惠券
     * @param order 订单
     * @param coupons 优惠券列表
     * @return 过滤结果
     */
    private List<OrderCouponVO> filterOrderCoupons(OrderDO order, List<OrderCouponVO> coupons) {
        List<Long> orderSkuIds = order.getProducts().stream().map(OrderProductDO::getSkuId).collect(Collectors.toList());
        return coupons.stream().filter(coupon -> {
            BelongTypeEnum belongType = BelongTypeEnum.parse(coupon.getBelongType());
            switch (belongType) {
                case PLATFORM:
                    PlatformCouponTypeEnum platformCouponType = PlatformCouponTypeEnum.parse(coupon.getCouponType());
                    switch (platformCouponType) {
                        case ZERO_DISCOUNT:
                            return orderSkuIds.contains(coupon.getSkuId());
                        case COMMON:
                            return true;
                    }
                    break;
                case MERCHANT:
                    MerchantCouponTypeEnum merchantCouponType = MerchantCouponTypeEnum.parse(coupon.getCouponType());
                    switch (merchantCouponType) {
                        case ZERO_DISCOUNT:
                        case COMMODITY:
                            return orderSkuIds.contains(coupon.getSkuId()) && order.getVendorMemberId().equals(coupon.getVendorMemberId()) && order.getVendorRoleId().equals(coupon.getVendorRoleId());
                        case COMMON:
                        case CATEGORY:
                        case BRAND:
                            return order.getVendorMemberId().equals(coupon.getVendorMemberId()) && order.getVendorRoleId().equals(coupon.getVendorRoleId());
                    }
                    break;
            }
            return false;
        }).collect(Collectors.toList());
    }

    /**
     * 查询订单优惠券列表
     *
     * @param order 订单
     * @return 查询结果
     */
    @Override
    public Wrapper<List<VendorOrderCouponVO>> findOrderCoupons(OrderDO order) {
        return Wrapper.success(orderCouponRepository.findByOrder(order).stream().map(coupon -> {
            VendorOrderCouponVO couponVO = new VendorOrderCouponVO();
            couponVO.setCouponId(coupon.getCouponId());
            couponVO.setName(coupon.getName());
            couponVO.setBelongType(coupon.getBelongType());
            couponVO.setBelongTypeName(BelongTypeEnum.getCodeMessage(coupon.getBelongType()));
            couponVO.setCouponType(coupon.getCouponType());
            couponVO.setCouponTypeName(coupon.getBelongType().equals(BelongTypeEnum.PLATFORM.getCode()) ? PlatformCouponTypeEnum.getCodeMessage(coupon.getCouponType()) : MerchantCouponTypeEnum.getCodeMessage(coupon.getCouponType()));
            couponVO.setAmount(NumberUtil.formatAmount(coupon.getAmount()));
            couponVO.setStartTime(coupon.getStartTime().format(OrderServiceContants.DEFAULT_TIME_FORMATTER));
            couponVO.setExpireTime(coupon.getExpireTime().format(OrderServiceContants.DEFAULT_TIME_FORMATTER));
            return couponVO;
        }).collect(Collectors.toList()));
    }
}
